package com.example.demo.executor;

import com.example.demo.DBServer.targetDatabase.DBServerDao;
import com.example.demo.entity.ExecuteInformationEntity;
import com.example.demo.entity.TableColumnEntity;
import com.example.demo.executor.backupDeal.BackupDataExecutor;
import com.example.demo.executor.backupDeal.BackupDataExecutorFactory;
import com.example.demo.executor.sqlGenerate.SqlGenerator;
import com.example.demo.executor.sqlGenerate.SqlGeneratorFactory;
import com.example.demo.typeEnums.ExecuteType;
import com.example.demo.typeEnums.ReservedType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.util.*;

@Component
public class SQLExecutor {

    @Autowired
    private DBServerDao dbServerDao;

    @Autowired
    private SqlGeneratorFactory sqlGeneratorFactory;

    @Autowired
    private BackupDataExecutorFactory backupDataExecutorFactory;

    @Value("${database.software.name}")
    private String databaseSoftwareName;

    private SqlGenerator sqlGenerator;

    @PostConstruct
    public void init(){
        sqlGenerator = sqlGeneratorFactory.getSqlGenerator(databaseSoftwareName);
        if(sqlGenerator == null){
            throw new NullPointerException();
        }
    }

    public Integer dataProcess(String tableName, String column,
                               List<Object> conditions, String processType, String backupDealType){
        if(ExecuteType.ARCHIVE.getName().equals(processType)){
            archiveDataByCondition(tableName,column,conditions,backupDealType);
        }
        return deleteDataByCondition(tableName,column,conditions);
    }

    public Integer archiveDataByCondition(String tableName, String column, List<Object> conditions, String backupDealType) {
        return archiveData(tableName,column,conditions,backupDealType);
    }

    public Integer deleteDataByCondition(String tableName, String column, List<Object> conditions) {
        return deleteData(tableName,column,conditions);
    }
    public Map<String, List<Object>> queryRelatedParam(String paramSql, List<String> columns){
        if(columns==null || columns.size()==0){
            return null;
        }
        Map<String, List<Object>> params = new HashMap<>();
        List<Map<String,Object>> queryResult = getParamsByCondition(paramSql);
        for(Map<String,Object> map : queryResult){
            for(String column : columns){
                if(null != map.get(column)) {
                    List<Object> list = params.computeIfAbsent(column, k -> new ArrayList<>());
                    list.add(map.get(column));
                }
            }
        }
        return params;
    }

    public List<Map<String,Object>> getParamsByCondition(String sql){
        return dbServerDao.getParamsByCondition(sql);
    }

    public Integer deleteData(String tableName, String column, List<Object> conditions){
        String deleteSql = sqlGenerator.generateDeleteSql(tableName,column,conditions);
        System.out.println(deleteSql);
        return 0;
//        return dbServerDao.deleteDataByCondition(deleteSql);
    }

    /**
     * 将满足表tableName的column字段中的数据在conditions里的进行备份
     * @param tableName
     * @param column
     * @param conditions
     * @param backupDealType
     * @return 返回备份的条数
     */
    public Integer archiveData(String tableName, String column, List<Object> conditions, String backupDealType){
        String backupTableName = tableName + "_backup";
        boolean tableExist = tableIsExist(backupTableName);
        // 备份表的结构和原表不一致时，需要对备份表的数据进行处理并删除备份表
        if(tableExist && isTableChanged(tableName)){
            BackupDataExecutor backupDataExecutor = backupDataExecutorFactory.getBackupDataExecutor(backupDealType);
            backupDataExecutor.backupTableDataDeal(backupTableName);
            tableExist = false;
        }
        // 备份表不存在时，重新生成备份表
        if(!tableExist){
            String createTableSql = sqlGenerator.generateCreateTableSql(tableName,backupTableName);
            dbServerDao.createTable(createTableSql);
        }
        String archiveSql = sqlGenerator.generateDataArchiveSql(tableName,backupTableName,column,conditions);
        System.out.println(archiveSql);
        return 0;
//        return dbServerDao.dataArchive(archiveSql);
    }

    /**
     * 得到符合条件的数据量
     */
    public Integer getNeedDealDataSize(String tableName, String condition){
        String querySizeSql = sqlGenerator.generateCountNeedDealSizeSql(tableName, condition);
        return dbServerDao.countBySql(querySizeSql);
    }

    /**
     * 得到符合条件的数据量
     */
    public Integer getNeedDealDataSize(ExecuteInformationEntity informationEntity, String condition){
        ReservedType reserveType = ReservedType.getReservedType(informationEntity.getReserveType(),null);
        String tableName = informationEntity.getTableName();
        String querySizeSql = sqlGenerator.generateCountNeedDealSizeSql(tableName, condition);
        return dbServerDao.countBySql(querySizeSql);
    }

    /**
     * 得到表中全部的数据量
     */
    public Integer getAmountOfDataInTable(String tableName){
        String queryAllSizeSql = sqlGenerator.generateCountAllDataSizeSql(tableName);
        return dbServerDao.countBySql(queryAllSizeSql);
    }

    /**
     * 检查table是否在数据库中存在
     * @param tableName 表名
     * @return true：数据库中存在此表，false：数据库中不存在此表
     */
    public boolean tableIsExist(String tableName){
        String checkSql = sqlGenerator.generateCheckTableExistSql(tableName);
        int count = dbServerDao.countBySql(checkSql);
        return count==1;
    }

    /**
     * 判断备份表是否发生改变
     * @param tableName
     * @return true：发生改变，false：未发生改变
     */
    public boolean isTableChanged(String tableName){
        // 获取备份表的字段
        String backUpTableName = tableName+"_backup";
        String backupColumnSql = sqlGenerator.generateQueryColumnInfoSql(backUpTableName);
        List<TableColumnEntity> backupColumnInfos = dbServerDao.getTableColumnInfo(backupColumnSql);
        if(backupColumnInfos.size()==0){
            return true;
        }
        Map<String,TableColumnEntity> backupColumnMap = new HashMap<>();
        for(TableColumnEntity info : backupColumnInfos){
            backupColumnMap.put(info.getColumnName(), info);
        }
        // 获取原始表的字段
        String originalColumnSql = sqlGenerator.generateQueryColumnInfoSql(tableName);
        List<TableColumnEntity> originalColumnInfos = dbServerDao.getTableColumnInfo(originalColumnSql);
        for(TableColumnEntity info : originalColumnInfos){
            String columnName = info.getColumnName();
            TableColumnEntity backupColumn = backupColumnMap.get(columnName);
            if(!info.equals(backupColumn)){
                return true;
            }
            backupColumnMap.remove(columnName);
        }
        if(backupColumnMap.size() != 0){
            return true;
        }
        return false;
    }
}
